/****************************************************************************
 * Copyright 2010 Huascar A. Sanchez                                        *
 *                                                                          *
 * Licensed under the Apache License, Version 2.0 (the "License");          *
 * you may not use this file except in compliance with the License.         *
 * You may obtain a copy of the License at                                  *
 *                                                                          *
 *     http://www.apache.org/licenses/LICENSE-2.0                           *
 *                                                                          *
 * Unless required by applicable law or agreed to in writing, software      *
 * distributed under the License is distributed on an "AS IS" BASIS,        *
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
 * See the License for the specific language governing permissions and      *
 * limitations under the License.                                           *
 ****************************************************************************/
package com.gotobject.greatq;

import com.gotobject.filter.internal.ToStrings;
import com.gotobject.greatq.datastore.DatastoreStatement;
import org.jiql.jdbc.ResultSet;
import org.jiql.jdbc.Statement;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;

import static com.gotobject.filter.internal.Pair.of;
import static com.gotobject.filter.internal.ToStrings.str;

/**
 * @author huascar.sanchez@gmail.com (Huascar A. Sanchez)
 */
class BatchedQueryImpl implements BatchedQuery {
    private final String        key;
    private final AtomicBoolean isBatch;
    private final Statement     internalStatement;
    private final AtomicBoolean isExecuted;
    private List<String>        sqls;

    BatchedQueryImpl(QueryServiceImpl oracleImpl, String key, List<String> sqls) throws SQLException {
        isExecuted          = new AtomicBoolean(false);
        this.sqls           = new ArrayList<String>(sqls);
        isBatch             = new AtomicBoolean(this.sqls.size() > 1);
        this.key            = key;
        internalStatement   = createStatement(oracleImpl.getSharedConnection());
    }

    private static Statement createStatement(Connection conn) throws SQLException {
        return (Statement) conn.createStatement();
    }

    private void ensureIsBatch() throws IllegalStateException {
        if(!inBatchMode()) throw new IllegalStateException("error:in batch mode");
    }

    Statement getInternalStatement(){
        return internalStatement;
    }

    @Override
    public String getTag() {
        return key;
    }
    

    public List<ResultSet> runAndGet() throws SQLException {
        ensureIsBatch();
        final DatastoreStatement statement;
        if(!isExecuted()){
            statement = new DatastoreStatement(getInternalStatement());
            for(String eachSql : sqls){
                 statement.addBatch(eachSql);
             }
            statement.executeBatch();
            isExecuted.set(!isExecuted.get());
            return statement.getAllResults();
        } else {
            return Collections.emptyList();
        }
    }

    @Override
    public boolean inBatchMode() {
        return isBatch.get();
    }

    public boolean isExecuted(){
        return isExecuted.get();
    }

    @Override
    public String toString() {
        return ToStrings.toString(
                this,
                of("key", getTag()),
                of("batched sqls", str(sqls)),
                of("isExecuted", str(isExecuted()))
        );
    }
}
